package org.jim.server.command.handler;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jim.common.ImConst;
import org.jim.common.ImAio;
import org.jim.common.ImPacket;
import org.jim.common.ImSessionContext;
import org.jim.common.ImStatus;
import org.jim.common.cache.redis.RedisCache;
import org.jim.common.cache.redis.RedisCacheManager;
import org.jim.common.message.MessageHelper;
import org.jim.common.packets.*;
import org.jim.common.protocol.IProtocol;
import org.jim.common.utils.ImKit;
import org.jim.common.utils.JsonKit;
import org.jim.server.command.AbstractCmdHandler;
import org.jim.server.command.CommandManager;
import org.jim.server.command.handler.processor.login.LoginCmdProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.utils.lock.SetWithLock;

import java.util.Date;
import java.util.List;

/**
 * 登录消息命令处理器
 *
 * @author WChao
 * @date 2018年4月10日 下午2:40:07
 */
public class LoginReqHandler extends AbstractCmdHandler {
    private static Logger log = LoggerFactory.getLogger(LoginReqHandler.class);

    RedisCache heartCache = new RedisCache(ImConst.HEART, 5000, 10000);

    RedisCache groupCache = RedisCacheManager.register(ImConst.GROUP, Integer.MAX_VALUE, Integer.MAX_VALUE);
    private final String SUBFIX = ":";

    @Override
    public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception {
        if (packet.getBody() == null) {
            Aio.remove(channelContext, "body is null");
            return null;
        }
        List<LoginCmdProcessor> loginProcessors = this.getProcessor(channelContext, LoginCmdProcessor.class);
        if (CollectionUtils.isEmpty(loginProcessors)) {
            log.info("登录失败,没有登录命令业务处理器!");
            Aio.remove(channelContext, "no login serviceHandler processor!");
            return null;
        }
        LoginCmdProcessor loginServiceHandler = loginProcessors.get(0);
        ImSessionContext imSessionContext = (ImSessionContext) channelContext.getAttribute();
        LoginReqBody loginReqBody = JsonKit.toBean(packet.getBody(), LoginReqBody.class);
//        System.out.println("loginReqBody:" + loginReqBody.toJsonString());
        LoginRespBody loginRespBody = loginServiceHandler.doLogin(loginReqBody, channelContext);
        String groupid = loginReqBody.getGroupid();
        if (loginRespBody == null || loginRespBody.getUser() == null) {
            log.info("登录失败, loginName:{}, password:{}", loginReqBody.getUserid(), groupid);
            if (loginRespBody == null) {
                loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP, ImStatus.C10008);
            }
            loginRespBody.clear();
            ImPacket loginRespPacket = new ImPacket(Command.COMMAND_LOGIN_RESP, loginRespBody.toByte());
            ImAio.bSend(channelContext, loginRespPacket);
            ImAio.remove(channelContext, "loginName and token is incorrect");
            return null;
        }
        User user = loginRespBody.getUser();
        String userId = user.getId();
        Group group = new Group(groupid, groupid);
        //通知相同在线id的用户被挤出登录
        SetWithLock<ChannelContext> toChannelContexts = ImAio.getChannelContextsByUserId(user.getId());
        if (toChannelContexts != null && toChannelContexts.size() > 0) {
            ChannelContext respchannelContext = toChannelContexts.getObj().iterator().next();
            ImSessionContext imSessionContexttow = (ImSessionContext) respchannelContext.getAttribute();
            User usertow = imSessionContexttow.getClient().getUser();
            RespBody respBody = new RespBody(Command.COMMAND_USEROFFLINE_RESP, ImStatus.C10046);
            ImPacket resppacket = new ImPacket(Command.COMMAND_USEROFFLINE_RESP, respBody.toByte());
            ImAio.bSend(respchannelContext, resppacket);
            ImAio.unbindUser(usertow.getId(), usertow.getGroupId());
            ImAio.remove(usertow.getId(), "");
        }
        // 解绑旧群组
        if (isStore() && !groupid.equals(user.getGroupId())) {
            groupCache.listRemove(user.getGroupId() + SUBFIX + ImConst.USER, userId);
        }
        imSessionContext.getClient().setUser(user);
        ImAio.bindUser(channelContext, userId, groupid, imConfig.getMessageHelper().getBindListener());
        ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ, JsonKit.toJsonBytes(group));
        // 绑定新群组
        try {
            JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class);
            joinGroupReqHandler.bindGroup(groupPacket, channelContext);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }

        loginServiceHandler.onSuccess(channelContext);
        //获取当前用户的离线消息
        //this.sendOfflineMessage(user);
        //心跳包
//        RedisCache heartCache = RedisCacheManager.getCache(ImConst.HEART);
        heartCache.hashSet("user", user.getId(), String.valueOf(new Date().getTime()));
        //loginRespBody.clear();
        ImPacket loginRespPacket = new ImPacket(Command.COMMAND_LOGIN_RESP, loginRespBody.toByte());
        return loginRespPacket;
    }

    /**
     * 初始化绑定或者解绑群组;
     */
//    public void bindUnbindGroup(ChannelContext channelContext, User user) throws Exception {
//        String userId = user.getId();
//        List<Group> groups = user.getGroups();
//        if (groups != null) {
//            boolean isStore = ImConst.ON.equals(imConfig.getIsStore());
//            MessageHelper messageHelper = null;
//            List<String> groupIds = null;
//            if (isStore) {
//                messageHelper = imConfig.getMessageHelper();
//                groupIds = messageHelper.getGroups(userId);
//            }
//            //绑定群组
//            for (Group group : groups) {
//                if (isStore && groupIds != null) {
//                    groupIds.remove(group.getGroupId());
//                }
//                //该数据不用放入缓存
//                ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ, JsonKit.toJsonBytes(group));
//                try {
//                    JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class);
//                    joinGroupReqHandler.bindGroup(groupPacket, channelContext);
//                } catch (Exception e) {
//                    log.error(e.toString(), e);
//                }
//            }
//            if (isStore && groupIds != null) {
//                for (String groupId : groupIds) {
//                    messageHelper.getBindListener().onAfterGroupUnbind(channelContext, groupId);
//                }
//            }
//        }
//    }
    private void sendOfflineMessage(User user) {
        UserMessageData messageData = null;
        MessageHelper messageHelper = imConfig.getMessageHelper();
        messageData = messageHelper.getFriendsOfflineMessage(user.getId());
        RespBody resPacket = null;
        resPacket = new RespBody(Command.COMMAND_GET_MESSAGE_RESP, ImStatus.C10016);
        resPacket.setData(messageData);
        ImPacket packet = new ImPacket(Command.COMMAND_GET_MESSAGE_RESP, resPacket.toByte());
        ImAio.sendToUser(user.getId(), packet);
    }

    /**
     * 是否开启持久化;
     *
     * @return
     */
    private boolean isStore() {
        return ImConst.ON.equals(imConfig.getIsStore());
    }

    @Override
    public Command command() {
        return Command.COMMAND_LOGIN_REQ;
    }
}
